<?php
/**
 * Created by PhpStorm.
 * User: yangfan
 * Date: 2020/1/15
 * Time: 12:05 PM
 */

namespace App\BO\PaymentState;

use App\BO\OrderStatus\OrderStatus;
use App\BO\PaymentState\Event\PaySuccessEvent;
use App\BO\PaymentState\Event\RefundSuccessEvent;
use App\BO\PaymentState\Pay\PayInfo;
use App\Entities\ConvertibleCardEntity;
use App\Entities\ConvertibleCardSaleRecordEntity;
use App\Entities\ConvertibleCardUseRecordEntity;
use App\Entities\ConvertibleCardUseRecordModel;
use App\Entities\GoodsPaymentEntity;
use App\Entities\GoodsPaymentModel;
use App\Entities\OrderEntity;
use App\Entities\PaymentEntity;
use App\Entities\PaymentModel;
use App\Entities\UserConvertibleCardEntity;
use App\Utils\Assert;
use App\Utils\CouponCodeFactoryUtil;
use Carbon\Carbon;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Log;

class PaymentState implements IJudgePaymentState
{
    use PaymentOperationTrait;

    /**
     * @var PaymentEntity
     */
    private $paymentEntity;

    /**
     * @var GoodsPaymentEntity
     */
    private $goodsPaymentEntity;

    public function __construct(PaymentEntity $paymentEntity)
    {
        $this->paymentEntity = $paymentEntity;
        $this->goodsPaymentEntity = GoodsPaymentEntity::findByTradeNo($paymentEntity->getTradeNo());
    }

    /**
     * 支付动作
     * @param PayInfo $payInfo
     * @throws \Exception
     */
    public function pay(PayInfo $payInfo)
    {
        $paymentEntity = $this->paymentEntity;
        if (PaymentModel::ORDER_TYPE_CLEAN_SERVICE == $paymentEntity->getOrderType()) {
            $this->cleanServicePay($payInfo);
        } elseif (PaymentModel::ORDER_TYPE_CONVERTIBLE_CARD == $paymentEntity->getOrderType()) {
            $this->convertibleCardPay($payInfo);
        } else {
            throw new \Exception('invalid pay type');
        }

        event(new PaySuccessEvent($paymentEntity));
        Log::info("paymentId = {$paymentEntity->getId()} 支付成功");
    }

    /**
     * @param PaymentEntity $paymentEntity
     * @param PayInfo $payInfo
     * @return PaymentEntity
     */
    private function syncPayInfo(PaymentEntity $paymentEntity, PayInfo $payInfo)
    {
        $paymentEntity->setOutTradeNo($payInfo->getPaymentNo());
        $paymentEntity->setPaymentMethod($payInfo->getPaymentMethod());
        $paymentEntity->setPaidAt($payInfo->getPaidAt());
        $paymentEntity->setState(PaymentStateDefinition::STATE_PAY_SUCCESS);
        return $paymentEntity;
    }

    private function convertibleCardPay(PayInfo $payInfo)
    {
        $paymentEntity = $this->paymentEntity;

        DB::beginTransaction();

        // 支付记录
        $paymentEntity = $this->syncPayInfo($paymentEntity, $payInfo);
        $paymentEntity->save();

        //
        $convertibleCardSaleRecordEntity = ConvertibleCardSaleRecordEntity::findByTradeNo($paymentEntity->getTradeNo());
        $convertibleCardSaleRecordEntity->setState(PaymentStateDefinition::STATE_PAY_SUCCESS);
        $convertibleCardSaleRecordEntity->setPaidAt($payInfo->getPaidAt());
        $convertibleCardSaleRecordEntity->save();

        // 增加销售个数
        $convertibleCardEntity = ConvertibleCardEntity::find($convertibleCardSaleRecordEntity->getConvertibleCardId());
        $convertibleCardEntity->addSoldCount(1);
        $convertibleCardEntity->save();

        $userId = $convertibleCardSaleRecordEntity->getUserId();

        // 用户记录
        $userConvertibleCardEntity = UserConvertibleCardEntity::getNewInstance();
        $userConvertibleCardEntity->setUserId($userId);
        $userConvertibleCardEntity->setConvertibleCardId($convertibleCardEntity->getId());
        $userConvertibleCardEntity->setCode(CouponCodeFactoryUtil::get12CodeMd5());
        $userConvertibleCardEntity->setTradeNo($paymentEntity->getTradeNo());
        $userConvertibleCardEntity->setExpireDate(Carbon::now()->addDays($convertibleCardEntity->getDuration())->toDateTimeString());
        $userConvertibleCardEntity->save();

        // 使用记录
        $convertibleCardUseRecordEntity = ConvertibleCardUseRecordEntity::getNewInstance();
        $convertibleCardUseRecordEntity->setUserId($userId);
        $convertibleCardUseRecordEntity->setConvertibleCardId($convertibleCardEntity->getId());
        $convertibleCardUseRecordEntity->setUserCardId($userConvertibleCardEntity->getId());
        $convertibleCardUseRecordEntity->setType(ConvertibleCardUseRecordModel::TYPE_BUY);
        $convertibleCardUseRecordEntity->setValue($convertibleCardEntity->getValue());
        $convertibleCardUseRecordEntity->setOperator('');
        $convertibleCardUseRecordEntity->setOrderId(0);
        $convertibleCardUseRecordEntity->save();

        DB::commit();
    }

    private function cleanServicePay(PayInfo $payInfo)
    {
        $paymentEntity = $this->paymentEntity;
        $goodsPaymentEntity = $this->goodsPaymentEntity;
        Assert::notNull($this->goodsPaymentEntity);

        DB::beginTransaction();
        $paymentEntity = $this->syncPayInfo($paymentEntity, $payInfo);
        $paymentEntity->save();

        $goodsPaymentEntity->setIsPaid(GoodsPaymentModel::IS_PAID);
        $goodsPaymentEntity->save();

        if ($goodsPaymentEntity->getIsMaster()) { // 是否为主订单
            $order = OrderEntity::find($goodsPaymentEntity->getOrderId());
            $orderStatus = new OrderStatus($order);
            $orderStatus->getOrderStateContext()->pay($payInfo);
        }
        DB::commit();
    }

    /**
     * 第三方退款确认操作
     */
    public function refundThirdPartConfirmSuccess()
    {
        try {
            DB::beginTransaction();
            $this->toRefundThirdPartConfirmSuccess($this->paymentEntity, $this->goodsPaymentEntity);
            event(new RefundSuccessEvent($this->paymentEntity));
            DB::commit();
        } catch (\Exception $e) {
            Log::info('第三方退款通知异常：' . $e->getMessage());
        }
    }

    /**
     * 退款失败确认操作
     */
    public function refundThirdPartConfirmFail()
    {
    }

    /**
     * 是否为待支付状态
     * @return bool
     */
    public function isWaitingPay()
    {
        return $this->paymentEntity->getState() == PaymentStateDefinition::STATE_WAITING_PAY;
    }

    /**
     * 是否为可退款状态
     * @return bool
     */
    public function isRefundAble()
    {
        return $this->paymentEntity->getState() == PaymentStateDefinition::STATE_PAY_SUCCESS;
    }

    /**
     * 是否已经支付
     * @return bool
     */
    public function isPaid()
    {
        return $this->paymentEntity->getPaidAt() ? true : false;
    }

    /**
     * 状态是否为退款等待第三方通知
     * @return bool
     */
    public function isRefundWaitingThirdPartNotify()
    {
        return $this->paymentEntity->getState() == PaymentStateDefinition::STATE_REFUND_WAITING_THIRD_PART_NOTIFY;
    }

    /**
     * 获取相关订单 ID
     * @return int
     */
    public function getOrderId()
    {
        return $this->goodsPaymentEntity->getOrderId();
    }
}
